package dominio.laberinto;

import java.util.Collection;
import java.util.ArrayList;
import java.util.Iterator;


import dominio.comida.BolaPacman;
import dominio.comida.Bolita;
import dominio.comida.Bolon;
import dominio.comun.IComestible;
import dominio.comun.IMolestable;
import dominio.comun.IMovible;
import dominio.comun.Posicion;
import dominio.fantasma.Fantasma;
import dominio.fantasma.IFantasma;
import dominio.juego.Juego;
import dominio.pacman.Pacman;

/**
 * @author RJC
 * @version 1.0
 * @created 16-jun-2012 11:59:28
 */
public final class Laberinto {

	private static Laberinto instance = null;
	private static Pacman miPacman;

	private Collection<ICasillero> misCasilleros;
	private Collection<IFantasma> misFantasmas;

	private int ancho;
	private int alto;
	private int anchoCasillero;
	private int altoCasillero;

	private ICasillero inicioPacman;
	private ICasillero inicioFantasmas;

	private Laberinto() {misFantasmas= new ArrayList<IFantasma>();}

	private static void createInstance() {
		if (instance == null) {
			instance = new Laberinto();
		}
	}

	public static Laberinto getInstance() {
		createInstance();
		return instance;
	}

	public Laberinto clone() throws CloneNotSupportedException {
		throw new CloneNotSupportedException();
	}

	/**
	 * 
	 * @param unaPosicion
	 *            Nos indica si algun desde la posicion origen es posible
	 *            moverse hacia la posicion de destino realizando un solo paso
	 */

	public boolean esVisitable(Posicion posicionOrigen, Posicion posicionDestino) {
		ICasillero casilleroABuscar = this.searchCasillero(posicionOrigen);
		if (casilleroABuscar != null)
			return casilleroABuscar.sePuedeTransitar(posicionDestino);
		else
			throw new RuntimeException(
					"La posicion desde la cual quiere moverse no es part de laberinto");
	}

	/**
	 * 
	 * @param unaPosicion
	 */
	public Collection<IComestible> getComestibles(Posicion unaPosicion) {
		Collection<IComestible> resultado = new ArrayList<IComestible>();
		ICasillero casillero = this.searchCasillero(unaPosicion);
		if (casillero != null) {
			BolaPacman bolita = casillero.getBola();
			if (bolita != null) {
				resultado.add(bolita);
			}
		}
		IFantasma fantasma = this.getFantasmaByPosicion(unaPosicion);
		if (fantasma != null) {
			resultado.add((IComestible) fantasma);
		}
		return resultado;
	}

	public Collection<IFantasma> getFantasmas() {
		return this.misFantasmas;
	}

	public Collection<IMovible> getMovibles() {
		Collection<IMovible> resultado = new ArrayList<IMovible>();
		resultado.add(miPacman);
		resultado.addAll((Collection<? extends IMovible>) misFantasmas);
		return resultado;

	}
	
	public Collection<IMolestable> getMolestables(){
		Collection<IMolestable> resultado = new ArrayList<IMolestable>();
		resultado.addAll((Collection<? extends IMolestable>)misFantasmas);
		return resultado;
	}

	public Pacman getPacman() {
		return miPacman;
	}

	public Posicion getPosCueva() {
		return this.inicioFantasmas.getPosicion();
	}

	public void chequearExistenBolas() {
		Iterator<ICasillero> iteradorCasilleros= misCasilleros.iterator();
		while (iteradorCasilleros.hasNext()){
			ICasillero casillaActual= iteradorCasilleros.next();
			if (casillaActual.getBola()!=null)
				return;
		}
		Juego.getInstance().gano();
	}

	public void setFantasmas(Collection<IMovible> fantasmas) {
		for (IMovible fantasma : fantasmas) {
			misFantasmas.add((IFantasma)fantasma);
		}		
	}
	
	public void setPacman(IMovible pacman){
		miPacman= (Pacman)pacman;
	}

	public ICasillero searchCasillero(Posicion posicionBuscada) {
		Iterator<ICasillero> itCasilleros = misCasilleros.iterator();
		while (itCasilleros.hasNext()) {
			ICasillero unCasillero = itCasilleros.next();
			if (unCasillero.getPosicion().comparateTo(posicionBuscada)) {
				return unCasillero;
			}
		}
		return null;
	}
	
	private IFantasma getFantasmaByPosicion(Posicion posicion) {
		for (IFantasma fantasma : this.misFantasmas) {
			if (fantasma.getPosicion().comparateTo(posicion)) {
				return fantasma;
			}
		}
		return null;
	}

	public int getAncho() {
		return ancho;
	}

	public void setAncho(int ancho) {
		this.ancho = ancho;
	}

	public int getAlto() {
		return alto;
	}

	public void setAlto(int alto) {
		this.alto = alto;
	}

	public int getAnchoCasillero() {
		return anchoCasillero;
	}

	public void setAnchoCasillero(int anchoCasillero) {
		this.anchoCasillero = anchoCasillero;
	}

	public int getAltoCasillero() {
		return altoCasillero;
	}

	public void setAltoCasillero(int altoCasillero) {
		this.altoCasillero = altoCasillero;
	}

	public ICasillero getInicioPacman() {
		return inicioPacman;
	}

	public void setInicioPacman(ICasillero inicioPacman) {
		this.inicioPacman = inicioPacman;
	}

	public ICasillero getInicioFantasmas() {
		return inicioFantasmas;
	}

	public void setInicioFantasmas(ICasillero inicioFantasmas) {
		this.inicioFantasmas = inicioFantasmas;
	}

	public Collection<ICasillero> getMisCasilleros() {
		return misCasilleros;
	}

	public void setMisCasilleros(Collection<ICasillero> misCasilleros) {
		this.misCasilleros = misCasilleros;
	}

}